home *** CD-ROM | disk | FTP | other *** search
- /* X-specific Lisp objects.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
- Copyright (C) 1995 Board of Trustees, University of Illinois
- Copyright (C) 1995 Tinker Systems
- Copyright (C) 1995 Ben Wing
-
- This file is part of XEmacs.
-
- XEmacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- XEmacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with XEmacs; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Synched up with: Not in FSF. */
-
- /* Authors: Jamie Zawinski, Chuck Thompson, Ben Wing */
-
- #include <config.h>
- #include "lisp.h"
-
- #include "device-x.h"
- #include "objects-x.h"
-
- #include "buffer.h"
- #include "insdel.h"
-
- int handle_nonfull_spec_fonts;
-
-
- /************************************************************************/
- /* color instances */
- /************************************************************************/
-
- /* Replacement for XAllocColor() that tries to return the nearest
- available color if the colormap is full. From FSF Emacs. */
-
- int
- allocate_nearest_color (Display *display, Colormap screen_colormap,
- XColor *color_def)
- {
- int status;
-
- status = XAllocColor (display, screen_colormap, color_def);
- if (!status)
- {
- /* If we got to this point, the colormap is full, so we're
- going to try and get the next closest color.
- The algorithm used is a least-squares matching, which is
- what X uses for closest color matching with StaticColor visuals. */
-
- XColor *cells;
- int no_cells;
- int nearest;
- long nearest_delta, trial_delta;
- int x;
-
- no_cells = XDisplayCells (display, XDefaultScreen (display));
- cells = (XColor *) alloca (sizeof (XColor) * no_cells);
-
- for (x = 0; x < no_cells; x++)
- cells[x].pixel = x;
-
- XQueryColors (display, screen_colormap, cells, no_cells);
- nearest = 0;
- /* I'm assuming CSE so I'm not going to condense this. */
- nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8))
- * ((color_def->red >> 8) - (cells[0].red >> 8)))
- +
- (((color_def->green >> 8) - (cells[0].green >> 8))
- * ((color_def->green >> 8) - (cells[0].green >> 8)))
- +
- (((color_def->blue >> 8) - (cells[0].blue >> 8))
- * ((color_def->blue >> 8) - (cells[0].blue >> 8))));
- for (x = 1; x < no_cells; x++)
- {
- trial_delta = ((((color_def->red >> 8) - (cells[x].red >> 8))
- * ((color_def->red >> 8) - (cells[x].red >> 8)))
- +
- (((color_def->green >> 8) - (cells[x].green >> 8))
- * ((color_def->green >> 8) - (cells[x].green >> 8)))
- +
- (((color_def->blue >> 8) - (cells[x].blue >> 8))
- * ((color_def->blue >> 8) - (cells[x].blue >> 8))));
- if (trial_delta < nearest_delta)
- {
- nearest = x;
- nearest_delta = trial_delta;
- }
- }
- color_def->red = cells[nearest].red;
- color_def->green = cells[nearest].green;
- color_def->blue = cells[nearest].blue;
- status = XAllocColor (display, screen_colormap, color_def);
- }
-
- return status;
- }
-
- static int
- x_initialize_color_instance (struct Lisp_Color_Instance *c, Lisp_Object name,
- Lisp_Object device, int no_error)
- {
- Display *dpy;
- Screen *xs;
- XColor color;
- Colormap cmap;
- int result;
-
- dpy = DEVICE_X_DISPLAY (XDEVICE (device));
- xs = DefaultScreenOfDisplay (dpy);
- cmap = DefaultColormapOfScreen (xs);
-
- memset (&color, 0, sizeof (color));
- result = XParseColor (dpy, cmap,
- string_ext_data (XSTRING (c->name)),
- &color);
- if (!result)
- {
- if (no_error)
- return 0;
- else
- signal_simple_error ("unrecognised color", c->name);
- }
- result = allocate_nearest_color (dpy, cmap, &color);
- if (!result)
- {
- if (no_error)
- return 0;
- else
- signal_simple_error ("couldn't allocate color", c->name);
- }
-
- /* Don't allocate the data until we're sure that we will succeed,
- or the finalize method may get fucked. */
- c->data = malloc_type (struct x_color_instance_data);
- COLOR_INSTANCE_X_COLOR (c) = color;
- return 1;
- }
-
- static void
- x_print_color_instance (struct Lisp_Color_Instance *c,
- Lisp_Object printcharfun,
- int escapeflag)
- {
- char buf[100];
- XColor color = COLOR_INSTANCE_X_COLOR (c);
- sprintf (buf, " %ld=(%X,%X,%X)",
- color.pixel, color.red, color.green, color.blue);
- write_c_string (buf, printcharfun);
- }
-
- static void
- x_finalize_color_instance (struct Lisp_Color_Instance *c)
- {
- Display *dpy = DEVICE_X_DISPLAY (XDEVICE (c->device));
-
- if (c->data)
- {
- XFreeColors (dpy,
- DefaultColormapOfScreen (DefaultScreenOfDisplay (dpy)),
- &COLOR_INSTANCE_X_COLOR (c).pixel, 1, 0);
- xfree (c->data);
- c->data = 0;
- }
- }
-
- /* Color instances are equal if they resolve to the same color on the
- screen (have the same RGB values). I imagine that
- "same RGV values" == "same cell in the colormap." Arguably we should
- be comparing their names instead. */
-
- static int
- x_color_instance_equal (struct Lisp_Color_Instance *c1,
- struct Lisp_Color_Instance *c2,
- int depth)
- {
- XColor color1 = COLOR_INSTANCE_X_COLOR (c1);
- XColor color2 = COLOR_INSTANCE_X_COLOR (c2);
- return ((color1.red == color2.red) &&
- (color1.green == color2.green) &&
- (color1.blue == color2.blue));
- }
-
- static unsigned long
- x_color_instance_hash (struct Lisp_Color_Instance *c, int depth)
- {
- XColor color = COLOR_INSTANCE_X_COLOR (c);
- return HASH3 (color.red, color.green, color.blue);
- }
-
- static Lisp_Object
- x_color_instance_rgb_components (struct Lisp_Color_Instance *c)
- {
- XColor color = COLOR_INSTANCE_X_COLOR (c);
- return (list3 (make_number (color.red),
- make_number (color.green),
- make_number (color.blue)));
- }
-
- static int
- x_valid_color_name_p (struct device *d, Lisp_Object color)
- {
- XColor c;
- Display *dpy = DEVICE_X_DISPLAY (d);
-
- return XParseColor (dpy,
- DefaultColormapOfScreen (DefaultScreenOfDisplay (dpy)),
- string_ext_data (XSTRING (color)), &c);
- }
-
-
- /************************************************************************/
- /* font instances */
- /************************************************************************/
-
- static int
- x_initialize_font_instance (struct Lisp_Font_Instance *f, Lisp_Object name,
- Lisp_Object device, int no_error)
- {
- Display *dpy;
- unsigned int def_char;
- #ifdef MULE
- XFontSet xf;
- char **missing_charset_list = 0;
- int missing_charset_count = 0;
- char *def_string = "";
- #else
- XFontStruct *xf;
- #endif
-
- dpy = DEVICE_X_DISPLAY (XDEVICE (device));
-
- #ifdef MULE
- xf = XCreateFontSet (dpy, string_ext_data (XSTRING (f->name)),
- &missing_charset_list, &missing_charset_count,
- &def_string);
- #else
- xf = XLoadQueryFont (dpy, string_ext_data (XSTRING (f->name)));
- #endif
-
- if (!xf)
- {
- if (no_error)
- return 0;
- #ifdef MULE
- if (!missing_charset_list)
- signal_simple_error ("couldn't load font set", f->name);
- else
- {
- Lisp_Object lost = Qnil;
- int i;
- for (i = missing_charset_count-1; i >= 0; i--)
- lost = Fcons (build_string (missing_charset_list[i]),
- lost);
- signal_simple_error_2
- ("couldn't load font set (missing required fonts)",
- f->name, lost);
- }
- #else
- signal_simple_error ("couldn't load font", f->name);
- #endif
- }
-
- #ifdef MULE
- if (!XExtentsOfFontSet (xf)->max_logical_extent.width)
- #else
- if (!xf->max_bounds.width)
- #endif
- {
- /* yes, this has been known to happen. */
- #ifdef MULE
- XFreeFontSet (dpy, xf);
- #else
- XFreeFont (dpy, xf);
- #endif
- if (no_error)
- return 0;
- signal_simple_error ("X font is too small", f->name);
- }
-
- /* Don't allocate the data until we're sure that we will succeed,
- or the finalize method may get fucked. */
- f->data = malloc_type (struct x_font_instance_data);
- FONT_INSTANCE_X_TRUENAME (f) = Qnil;
- FONT_INSTANCE_X_FONT (f) = xf;
- #ifdef MULE
- f->height = XExtentsOfFontSet(xf)->max_logical_extent.height;
- f->ascent = -XExtentsOfFontSet(xf)->max_logical_extent.y;
- f->descent = xf->height - xf->ascent;
- #else
- f->ascent = xf->ascent;
- f->descent = xf->descent;
- f->height = xf->ascent + xf->descent;
- #endif
- /* We used to use 'N' as the default character but that ends up
- being a little wide as a default when variable width fonts are
- used. 'n' seems to give a much better average. */
- #ifdef MULE
- {
- XFontStruct **fstruct_l;
- char **fname_l;
- int n;
- n= XFontsOfFontSet (xf, &fstruct_l, &fname_l);
- if (n == 0)
- abort ();
- /* first font is iso-8859 and that's the width that we want to use */
- lf->width = fstruct_l[0]->max_bounds.width;
- def_char =
- ((fstruct_l[0]->default_char >= fstruct_l[0]->min_char_or_byte2 &&
- fstruct_l[0]->default_char <= fstruct_l[0]->max_char_or_byte2)
- ? fstruct_l[0]->default_char
- : 'n');
- }
- #else
- /* Old versions of the R5 font server have garbage (>63k) as def_char. */
- def_char = ((xf->default_char >= xf->min_char_or_byte2 &&
- xf->default_char <= xf->max_char_or_byte2)
- ? xf->default_char
- : 'n');
- once_more:
- f->width = (xf->per_char
- /* #### what are we supposed to do with byte1 here? */
- ? xf->per_char [def_char - xf->min_char_or_byte2].width
- : xf->max_bounds.width);
-
- /* Some fonts have a default char whose width is 0. This is no good.
- If that's the case, first try 'n' as the default char, and if n has
- 0 width too (unlikely) then just use the max width. */
- if (f->width == 0)
- {
- if (def_char == 'n')
- f->width = xf->max_bounds.width;
- else
- {
- def_char = 'n';
- goto once_more;
- }
- }
- #endif
- #ifdef MULE
- /* !!#### Review this. */
- f->proportional_p = 1;
- #else
- /* If all characters don't exist then there could potentially be
- 0-width characters lurking out there. Not setting this flag
- trips an optimization that would make them appear to have width
- to redisplay. This is bad. So we set it if not all characters
- have the same width or if not all characters are defined.
- */
- /* #### This sucks. There is a measurable performance increase
- when using proportional width fonts if this flag is not set.
- Unfortunately so many of the fucking X fonts are not fully
- defined that we could almost just get rid of this damn flag and
- make it an assertion. */
- f->proportional_p = (xf->min_bounds.width != xf->max_bounds.width ||
- (handle_nonfull_spec_fonts &&
- !xf->all_chars_exist));
- #endif
-
- return 1;
- }
-
- static void
- x_mark_font_instance (struct Lisp_Font_Instance *f,
- void (*markobj) (Lisp_Object))
- {
- ((markobj) (FONT_INSTANCE_X_TRUENAME (f)));
- }
-
- static void
- x_print_font_instance (struct Lisp_Font_Instance *f,
- Lisp_Object printcharfun,
- int escapeflag)
- {
- char buf[200];
- sprintf (buf, " 0x%lx", (unsigned long) FONT_INSTANCE_X_FONT (f)->fid);
- write_c_string (buf, printcharfun);
- }
-
- static void
- x_finalize_font_instance (struct Lisp_Font_Instance *f)
- {
- Display *dpy = DEVICE_X_DISPLAY (XDEVICE (f->device));
-
- if (f->data)
- {
- # ifdef MULE
- XFreeFontSet (dpy, FONT_INSTANCE_X_FONT (f));
- # else
- XFreeFont (dpy, FONT_INSTANCE_X_FONT (f));
- # endif
- xfree (f->data);
- f->data = 0;
- }
- }
-
- /* Determining the truename of a font is hard. (Big surprise.)
-
- By "truename" we mean an XLFD-form name which contains no wildcards, yet
- which resolves to *exactly* the same font as the one which we already have
- the (probably wildcarded) name and `XFontStruct' of.
-
- One might think that the first font returned by XListFonts would be the one
- that XOpenFont would pick. Apparently this is the case on some servers,
- but not on others. It would seem not to be specified.
-
- The MIT R5 server sometimes appears to be picking the lexicographically
- smallest font which matches the name (thus picking "adobe" fonts before
- "bitstream" fonts even if the bitstream fonts are earlier in the path, and
- also picking 100dpi adobe fonts over 75dpi adobe fonts even though the
- 75dpi are in the path earlier) but sometimes appears to be doing something
- else entirely (for example, removing the bitsream fonts from the path will
- cause the 75dpi adobe fonts to be used instead of the100dpi, even though
- their relative positions in the path (and their names!) have not changed).
-
- The documentation for XSetFontPath() seems to indicate that the order of
- entries in the font path means something, but it's pretty noncommital about
- it, and the spirit of the law is apparently not being obeyed...
-
- All the fonts I've seen have a property named `FONT' which contains the
- truename of the font. However, there are two problems with using this: the
- first is that the X Protocol Document is quite explicit that all properties
- are optional, so we can't depend on it being there. The second is that
- it's concievable that this alleged truename isn't actually accessible as a
- font, due to some difference of opinion between the font designers and
- whoever installed the font on the system.
-
- So, our first attempt is to look for a FONT property, and then verify that
- the name there is a valid name by running XListFonts on it. There's still
- the potential that this could be true but we could still be being lied to,
- but that seems pretty remote.
-
- Late breaking news: I've gotten reports that SunOS 4.1.3U1
- with OpenWound 3.0 has a font whose truename is really
- "-Adobe-Courier-Medium-R-Normal--12-120-75-75-M-70-ISO8859-1"
- but whose FONT property contains "Courier".
-
- So we disbelieve the FONT property unless it begins with a dash and
- is more than 30 characters long. X Windows: The defacto substandard.
- X Windows: Complex nonsolutions to simple nonproblems. X Windows:
- Live the nightmare.
-
- If the FONT property doesn't exist, then we try and construct an XLFD name
- out of the other font properties (FOUNDRY, FAMILY_NAME, WEIGHT_NAME, etc).
- This is necessary at least for some versions of OpenWound. But who knows
- what the future will bring.
-
- If that doesn't work, then we use XListFonts and either take the first font
- (which I think is the most sensible thing) or we find the lexicographically
- least, depending on whether the preprocessor constant `XOPENFONT_SORTS' is
- defined. This sucks because the two behaviors are a property of the server
- being used, not the architecture on which emacs has been compiled. Also,
- as I described above, sorting isn't ALWAYS what the server does. Really it
- does something seemingly random. There is no reliable way to win if the
- FONT property isn't present.
-
- Another possibility which I haven't bothered to implement would be to map
- over all of the matching fonts and find the first one that has the same
- character metrics as the font we already have loaded. Even if this didn't
- return exactly the same font, it would at least return one whose characters
- were the same sizes, which would probably be good enough.
-
- More late-breaking news: on RS/6000 AIX 3.2.4, the expression
- XLoadQueryFont (dpy, "-*-Fixed-Medium-R-*-*-*-130-75-75-*-*-ISO8859-1")
- actually returns the font
- -Misc-Fixed-Medium-R-Normal--13-120-75-75-C-80-ISO8859-1
- which is crazy, because that font doesn't even match that pattern! It is
- also not included in the output produced by `xlsfonts' with that pattern.
-
- So this is yet another example of XListFonts() and XOpenFont() using
- completely different algorithms. This, however, is a goofier example of
- this bug, because in this case, it's not just the search order that is
- different -- the sets don't even intersect.
-
- If anyone has any better ideas how to do this, or any insights on what it is
- that the various servers are actually doing, please let me know! -- jwz. */
-
- static int
- valid_x_font_name_p (Display *dpy, char *name)
- {
- /* Maybe this should be implemented by callign XLoadFont and trapping
- the error. That would be a lot of work, and wasteful as hell, but
- might be more correct.
- */
- int nnames = 0;
- char **names;
- if (! name)
- return 0;
- names = XListFonts (dpy, name, 1, &nnames);
- if (names)
- XFreeFontNames (names);
- return (nnames != 0);
- }
-
- static char *
- truename_via_FONT_prop (Display *dpy, XFontStruct *font)
- {
- unsigned long value = 0;
- char *result = 0;
- if (XGetFontProperty (font, XA_FONT, &value))
- result = XGetAtomName (dpy, value);
- /* result is now 0, or the string value of the FONT property. */
- if (result)
- {
- /* Verify that result is an XLFD name (roughly...) */
- if (result [0] != '-' || strlen (result) < (unsigned int) 30)
- {
- XFree (result);
- result = 0;
- }
- }
- return result; /* this must be freed by caller if non-0 */
- }
-
- static char *
- truename_via_random_props (Display *dpy, XFontStruct *font)
- {
- struct device *d = get_device_from_display (dpy);
- unsigned long value = 0;
- char *foundry, *family, *weight, *slant, *setwidth, *add_style;
- unsigned long pixel, point, res_x, res_y;
- char *spacing;
- unsigned long avg_width;
- char *registry, *encoding;
- char composed_name [2048];
- int ok = 0;
- char *result;
-
- #define get_string(atom,var) \
- if (XGetFontProperty (font, (atom), &value)) \
- var = XGetAtomName (dpy, value); \
- else { \
- var = 0; \
- goto FAIL; }
- #define get_number(atom,var) \
- if (!XGetFontProperty (font, (atom), &var) || \
- var > 999) \
- goto FAIL;
-
- foundry = family = weight = slant = setwidth = 0;
- add_style = spacing = registry = encoding = 0;
-
- get_string (DEVICE_XATOM_FOUNDRY (d), foundry);
- get_string (DEVICE_XATOM_FAMILY_NAME (d), family);
- get_string (DEVICE_XATOM_WEIGHT_NAME (d), weight);
- get_string (DEVICE_XATOM_SLANT (d), slant);
- get_string (DEVICE_XATOM_SETWIDTH_NAME (d), setwidth);
- get_string (DEVICE_XATOM_ADD_STYLE_NAME (d), add_style);
- get_number (DEVICE_XATOM_PIXEL_SIZE (d), pixel);
- get_number (DEVICE_XATOM_POINT_SIZE (d), point);
- get_number (DEVICE_XATOM_RESOLUTION_X (d), res_x);
- get_number (DEVICE_XATOM_RESOLUTION_Y (d), res_y);
- get_string (DEVICE_XATOM_SPACING (d), spacing);
- get_number (DEVICE_XATOM_AVERAGE_WIDTH (d), avg_width);
- get_string (DEVICE_XATOM_CHARSET_REGISTRY (d), registry);
- get_string (DEVICE_XATOM_CHARSET_ENCODING (d), encoding);
- #undef get_number
- #undef get_string
-
- sprintf (composed_name,
- "-%s-%s-%s-%s-%s-%s-%ld-%ld-%ld-%ld-%s-%ld-%s-%s",
- foundry, family, weight, slant, setwidth, add_style, pixel,
- point, res_x, res_y, spacing, avg_width, registry, encoding);
- ok = 1;
-
- FAIL:
- if (ok)
- {
- int L = strlen (composed_name) + 1;
- result = xmalloc (L);
- strncpy (result, composed_name, L);
- }
- else
- result = 0;
-
- if (foundry) XFree (foundry);
- if (family) XFree (family);
- if (weight) XFree (weight);
- if (slant) XFree (slant);
- if (setwidth) XFree (setwidth);
- if (add_style) XFree (add_style);
- if (spacing) XFree (spacing);
- if (registry) XFree (registry);
- if (encoding) XFree (encoding);
-
- return result;
- }
-
- /* Unbounded, for sufficiently small values of infinity... */
- #define MAX_FONT_COUNT 5000
-
- static char *
- truename_via_XListFonts (Display *dpy, char *font_name)
- {
- char *result = 0;
- char **names;
- int count = 0;
-
- #ifndef XOPENFONT_SORTS
- /* In a sensible world, the first font returned by XListFonts()
- would be the font that XOpenFont() would use. */
- names = XListFonts (dpy, font_name, 1, &count);
- if (count) result = names [0];
- #else
- /* But the world I live in is much more perverse. */
- names = XListFonts (dpy, font_name, MAX_FONT_COUNT, &count);
- while (count--)
- /* If names[count] is lexicographically less than result, use it.
- (#### Should we be comparing case-insensitively?) */
- if (result == 0 || (strcmp (result, names [count]) < 0))
- result = names [count];
- #endif
-
- if (result)
- result = xstrdup (result);
- if (names)
- XFreeFontNames (names);
-
- return result; /* this must be freed by caller if non-0 */
- }
-
- static Lisp_Object
- x_font_truename (Display *dpy, char *name, XFontStruct *font)
- {
- char *truename_FONT = 0;
- char *truename_random = 0;
- char *truename = 0;
-
- /* The search order is:
- - if FONT property exists, and is a valid name, return it.
- - if the other props exist, and add up to a valid name, return it.
- - if we find a matching name with XListFonts, return it.
- - if FONT property exists, return it regardless.
- - if other props exist, return the resultant name regardless.
- - else return 0.
- */
-
- truename = truename_FONT = truename_via_FONT_prop (dpy, font);
- if (truename && !valid_x_font_name_p (dpy, truename))
- truename = 0;
- if (!truename)
- truename = truename_random = truename_via_random_props (dpy, font);
- if (truename && !valid_x_font_name_p (dpy, truename))
- truename = 0;
- if (!truename && name)
- truename = truename_via_XListFonts (dpy, name);
-
- if (!truename)
- {
- /* Gag - we weren't able to find a seemingly-valid truename.
- Well, maybe we're on one of those braindead systems where
- XListFonts() and XLoadFont() are in violent disagreement.
- If we were able to compute a truename, try using that even
- if evidence suggests that it's not a valid name - because
- maybe it is, really, and that's better than nothing.
- X Windows: You'll envy the dead.
- */
- if (truename_FONT)
- truename = truename_FONT;
- else if (truename_random)
- truename = truename_random;
- }
-
- /* One or both of these are not being used - free them. */
- if (truename_FONT && truename_FONT != truename)
- XFree (truename_FONT);
- if (truename_random && truename_random != truename)
- XFree (truename_random);
-
- if (truename)
- {
- Lisp_Object result = build_string (truename);
- xfree (truename);
- return result;
- }
- else
- return Qnil;
- }
-
- static Lisp_Object
- x_font_instance_truename (struct Lisp_Font_Instance *f, int no_error)
- {
- struct device *d = XDEVICE (f->device);
-
- if (NILP (FONT_INSTANCE_X_TRUENAME (f)))
- {
- Display *dpy = DEVICE_X_DISPLAY (d);
- char *name =
- (char *) string_data (XSTRING (f->name));
- #ifdef MULE
- {
- XFontStruct **fonts;
- char **names;
- int count = XFontsOfFontSet (FONT_INSTANCE_X_FONT (f), &fonts, &names);
- Lisp_Object *lnames =
- (Lisp_Object *) alloca (count * 2 * sizeof (Lisp_Object));
- Lisp_Object comma = build_string (","); /* Q'ing this would be silly */
- int i, j;
- for (i = 0, j = 0; i < count; i++)
- {
- Lisp_Object tn = x_font_truename (dpy, names [i], fonts [i]);
- if (NILP (tn)) tn = build_string (names [i]);
- if (i != 0) lnames [j++] = comma;
- lnames [j++] = tn;
- }
- FONT_INSTANCE_X_TRUENAME (f) = Fconcat (j, lnames);
- }
- #else
- {
- FONT_INSTANCE_X_TRUENAME (f) =
- x_font_truename (dpy, name, FONT_INSTANCE_X_FONT (f));
- }
- #endif
- if (NILP (FONT_INSTANCE_X_TRUENAME (f)))
- {
- if (no_error)
- /* Ok, just this once, return the font name as the truename.
- (This is only used by Fequal() right now.) */
- return f->name;
- else
- {
- Lisp_Object font_instance = Qnil;
- XSETFONT_INSTANCE (font_instance, f);
- signal_simple_error ("couldn't determine font truename",
- font_instance);
- }
- }
- }
- return (FONT_INSTANCE_X_TRUENAME (f));
- }
-
- static Lisp_Object
- x_font_instance_properties (struct Lisp_Font_Instance *f)
- {
- struct device *d = XDEVICE (f->device);
- int i;
- Lisp_Object result = Qnil;
- XFontProp *props;
- Display *dpy;
-
- dpy = DEVICE_X_DISPLAY (d);
- /* #### Won't work under Mule. */
- props = FONT_INSTANCE_X_FONT (f)->properties;
- for (i = FONT_INSTANCE_X_FONT (f)->n_properties - 1; i >= 0; i--)
- {
- char *name_str = 0;
- char *val_str = 0;
- Lisp_Object name, value;
- Atom atom = props [i].name;
- name_str = XGetAtomName (dpy, atom);
- name = (name_str ? intern (name_str) : Qnil);
- if (name_str &&
- (atom == XA_FONT ||
- atom == DEVICE_XATOM_FOUNDRY (d) ||
- atom == DEVICE_XATOM_FAMILY_NAME (d) ||
- atom == DEVICE_XATOM_WEIGHT_NAME (d) ||
- atom == DEVICE_XATOM_SLANT (d) ||
- atom == DEVICE_XATOM_SETWIDTH_NAME (d) ||
- atom == DEVICE_XATOM_ADD_STYLE_NAME (d) ||
- atom == DEVICE_XATOM_SPACING (d) ||
- atom == DEVICE_XATOM_CHARSET_REGISTRY (d) ||
- atom == DEVICE_XATOM_CHARSET_ENCODING (d) ||
- !strcmp (name_str, "CHARSET_COLLECTIONS") ||
- !strcmp (name_str, "FONTNAME_REGISTRY") ||
- !strcmp (name_str, "CLASSIFICATION") ||
- !strcmp (name_str, "COPYRIGHT") ||
- !strcmp (name_str, "DEVICE_FONT_NAME") ||
- !strcmp (name_str, "FULL_NAME") ||
- !strcmp (name_str, "MONOSPACED") ||
- !strcmp (name_str, "QUALITY") ||
- !strcmp (name_str, "RELATIVE_SET") ||
- !strcmp (name_str, "RELATIVE_WEIGHT") ||
- !strcmp (name_str, "STYLE")))
- {
- val_str = XGetAtomName (dpy, props [i].card32);
- value = (val_str ? build_string (val_str) : Qnil);
- }
- else
- value = make_number (props [i].card32);
- if (name_str) XFree (name_str);
- result = Fcons (Fcons (name, value), result);
- }
- return result;
- }
-
- static Lisp_Object
- x_list_fonts (Lisp_Object pattern, Lisp_Object device)
- {
- char **names;
- int count = 0;
- Lisp_Object result = Qnil;
-
- names = XListFonts (DEVICE_X_DISPLAY (XDEVICE (device)),
- string_ext_data (XSTRING (pattern)),
- MAX_FONT_COUNT, &count);
- while (count--)
- result = Fcons (build_string (names [count]), result);
- if (names)
- XFreeFontNames (names);
- return result;
- }
-
-
- #ifdef EPOCH
-
- /************************************************************************/
- /* X resources */
- /************************************************************************/
-
- Lisp_Object Qx_resourcep;
- static Lisp_Object mark_x_resource (Lisp_Object, void (*) (Lisp_Object));
- static void print_x_resource (Lisp_Object, Lisp_Object, int);
- static void finalize_x_resource (void *, int);
- static int x_resource_equal (Lisp_Object o1, Lisp_Object o2, int depth);
- static unsigned long x_resource_hash (Lisp_Object obj, int depth);
- DEFINE_LRECORD_IMPLEMENTATION ("x-resource", x_resource,
- mark_x_resource, print_x_resource,
- finalize_x_resource, x_resource_equal,
- x_resource_hash, struct Lisp_X_Resource);
-
- static Lisp_Object
- mark_x_resource (Lisp_Object obj, void (*markobj) (Lisp_Object))
- {
- return Qnil;
- }
-
- static void
- print_x_resource (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
- {
- char buf[100];
- char *default_string = "Resource";
- Lisp_Object atom_symbol;
- struct device *d = get_x_device (Qnil);
-
- if (print_readably)
- error ("printing unreadable object #<x-resource 0x%x>",
- XX_RESOURCE (obj)->xid);
-
- atom_symbol = x_atom_to_symbol (d, XX_RESOURCE (obj)->type);
- sprintf (buf, "#<x-resource %s 0x%x>",
- (NILP (atom_symbol)
- ? default_string
- : string_data (XSTRING (Fsymbol_name (atom_symbol)))),
- XX_RESOURCE (obj)->xid);
- write_c_string (buf, printcharfun);
- }
-
- static void
- finalize_x_resource (void *header, int for_disksave)
- {
- }
-
- static int
- x_resource_equal (Lisp_Object o1, Lisp_Object o2, int depth)
- {
- return (XX_RESOURCE (o1)->xid == XX_RESOURCE (o2)->xid);
- }
-
- static unsigned long
- x_resource_hash (Lisp_Object obj, int depth)
- {
- return XX_RESOURCE (obj)->xid;
- }
-
- /*
- * Epoch equivalent: epoch::resourcep
- */
- DEFUN ("x-resource-p", Fx_resource_p, Sx_resource_p, 1, 1, 0,
- "Return non-nil if OBJECT is an X resource object.")
- (object)
- Lisp_Object object;
- {
- return (X_RESOURCEP (object) ? Qt : Qnil);
- }
-
- /*
- * Epoch equivalent: epoch::set-resource-type
- */
- DEFUN ("x-set-x-resource-type", Fx_set_x_resource_type, Sx_set_x_resource_type,
- 2, 2, 0,
- "Set the type of RESOURE to TYPE. The new type must be an atom.")
- (resource, type)
- Lisp_Object resource, type;
- {
- CHECK_X_RESOURCE (resource, 0);
- CHECK_X_RESOURCE (type, 0);
-
- if (XX_RESOURCE (type)->type != XA_ATOM)
- error ("New type must be an atom");
-
- XX_RESOURCE (resource)->type = XX_RESOURCE (type)->xid;
- return resource;
- }
-
- #endif /* EPOCH */
-
-
- /************************************************************************/
- /* initialization */
- /************************************************************************/
-
- void
- syms_of_objects_x (void)
- {
- #ifdef EPOCH
- defsymbol (&Qx_resourcep, "x-resource-p");
- defsubr (&Sx_resource_p);
- defsubr (&Sx_set_x_resource_type);
- #endif /* EPOCH */
- }
-
- void
- device_type_create_objects_x (void)
- {
- /* object methods */
-
- DEVICE_HAS_METHOD (x, initialize_color_instance);
- DEVICE_HAS_METHOD (x, print_color_instance);
- DEVICE_HAS_METHOD (x, finalize_color_instance);
- DEVICE_HAS_METHOD (x, color_instance_equal);
- DEVICE_HAS_METHOD (x, color_instance_hash);
- DEVICE_HAS_METHOD (x, color_instance_rgb_components);
- DEVICE_HAS_METHOD (x, valid_color_name_p);
-
- DEVICE_HAS_METHOD (x, initialize_font_instance);
- DEVICE_HAS_METHOD (x, mark_font_instance);
- DEVICE_HAS_METHOD (x, print_font_instance);
- DEVICE_HAS_METHOD (x, finalize_font_instance);
- DEVICE_HAS_METHOD (x, font_instance_truename);
- DEVICE_HAS_METHOD (x, font_instance_properties);
- DEVICE_HAS_METHOD (x, list_fonts);
- }
-
- void
- vars_of_objects_x (void)
- {
- DEFVAR_BOOL ("x-handle-non-fully-specified-fonts",&handle_nonfull_spec_fonts,
- "If this is true then fonts which do not have all characters specified\n\
- will be considered to be proportional width even if they are actually\n\
- fixed-width. If this is not done then characters which are supposed to\n\
- have 0 width may appear to actually have some width.\n\
- \n\
- Note: While setting this to t guarantees correct output in all\n\
- circumstances, it also causes a noticeable performance hit when using\n\
- fixed-width fonts. Since most people don't use characters which could\n\
- cause problems this is set to nil by default.");
- handle_nonfull_spec_fonts = 0;
- }
-
-
- void
- Xatoms_of_objects_x (struct device *d)
- {
- #define ATOM(x) XInternAtom (DEVICE_X_DISPLAY (d), (x), False)
-
- DEVICE_XATOM_FOUNDRY (d) = ATOM ("FOUNDRY");
- DEVICE_XATOM_FAMILY_NAME (d) = ATOM ("FAMILY_NAME");
- DEVICE_XATOM_WEIGHT_NAME (d) = ATOM ("WEIGHT_NAME");
- DEVICE_XATOM_SLANT (d) = ATOM ("SLANT");
- DEVICE_XATOM_SETWIDTH_NAME (d) = ATOM ("SETWIDTH_NAME");
- DEVICE_XATOM_ADD_STYLE_NAME (d) = ATOM ("ADD_STYLE_NAME");
- DEVICE_XATOM_PIXEL_SIZE (d) = ATOM ("PIXEL_SIZE");
- DEVICE_XATOM_POINT_SIZE (d) = ATOM ("POINT_SIZE");
- DEVICE_XATOM_RESOLUTION_X (d) = ATOM ("RESOLUTION_X");
- DEVICE_XATOM_RESOLUTION_Y (d) = ATOM ("RESOLUTION_Y");
- DEVICE_XATOM_SPACING (d) = ATOM ("SPACING");
- DEVICE_XATOM_AVERAGE_WIDTH (d) = ATOM ("AVERAGE_WIDTH");
- DEVICE_XATOM_CHARSET_REGISTRY (d) = ATOM ("CHARSET_REGISTRY");
- DEVICE_XATOM_CHARSET_ENCODING (d) = ATOM ("CHARSET_ENCODING");
- }
-